﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace TouchUmlUI
{
    public class AssociableObj : UMLObj
    {

        public bool corrected = false;
        public int[] count = { 0, 0, 0, 0 };
        public bool callReturn = true;
        public int[] es; // east west points
        public int[] ns; // north south points        

        // Association
        public List<AssociationObj> associationObj = new List<AssociationObj>();      

        public void BringObjectsToFront()
        {
            foreach (AssociationObj aObj in associationObj)
            {
                aObj.fromRef.BringToFront();
                aObj.toRef.BringToFront();
            }
        }

        public AssociableObj(GUML aguml) : base(aguml) { }

        public void addAsociation(AssociationObj aObj)
        {
            associationObj.Add(aObj);
        }

        public void calculatePoints() 
        {            
            int c = associationObj.Count;
            es = ns = null;
            es = new int[c];
            ns = new int[c];
            int startPointY;
            int startPointX;
            startPointY = c % 2 == 0 ? -10 : 0;
            startPointX = c % 2 == 0 ? -10 : 0;
            startPointY = (int)(this.getHeight() / 2.0f) + startPointY;
            startPointX = (int)(this.getWidth() / 2.0f) + startPointX;
            for (int i = 0; i < c; i++)
            {
                es[i] = startPointY;
                ns[i] = startPointX;
                startPointX += 20;
                startPointY += 20;
            }
        }

        public int getAssociationId(AssociationObj aObj)
        {
            for (int i = 0; i < associationObj.Count; i++)
            {
                if (aObj.Equals(associationObj[i]))
                    return i;
            }
            return -1;
        }

        public void updateDependencyProperties(bool callReturn)
        {
            base.updateDependencyProperties();
            this.callReturn = callReturn;
            updateDependencyProperties();
            callReturn = true;
        }

        public void calculateNewPoints()
        {
            calculatePoints();
            for (int i = 0; i < associationObj.Count; i++)
            {
                AssociationObj aObj = associationObj[i];
                    if (aObj.fromRef.Equals(this)) 
                    {
                        aObj.FROMES = es[i];
                        aObj.FROMNS = ns[i];
                    }
                    else if (aObj.toRef.Equals(this))
                    {
                        aObj.TOES = es[i];
                        aObj.TONS = ns[i];
                    }
            }
        }

        public override void updateDependencyProperties()
        {            
            calculateNewPoints();
            base.updateDependencyProperties();
            if (associationObj == null) return;                        

            for (int aId = 0;aId<associationObj.Count;aId++)
            {
                    AssociationObj aObj = associationObj[aId];                                      
                    AssociableObj a1, a2;                                        
                                        
                    a1 = aObj.fromRef as AssociableObj;
                    a2 = aObj.toRef as AssociableObj;

                    a1.calculatePoints();
                    a2.calculatePoints();
                                        
                    if (aObj.getLineType() == TouchUmlUI.AssociationObj.LineType.CORNERED)
                    {                                                
                            double x1, y1, x2, y2, x3, y3, x4, y4;
                            x1 = x2 = x3 = x4 = y1 = y2 = y3 = y4 = 0;

                            if ((a2.getY() + a2.getHeight() > a1.getY()) && (a2.getY() < a1.getY() + a1.getHeight())) 
                            {
                                if (a1.getX() + a1.getWidth() / 2.0f < a2.getX() + a2.getWidth() / 2.0f)
                                {                                    
                                    x1 = a1.getX() + a1.getWidth();                                    
                                    y1 = a1.getY() + aObj.FROMES;
                                    x4 = a2.getX();
                                    y3 = a2.getY() + aObj.TOES;
                                    aObj.setFromConnectionPoint(TouchUmlUI.AssociationObj.ConnectionPoint.EAST);
                                    aObj.setPointFrom(x1, y1);                                    
                                    aObj.setToConnectionPoint(TouchUmlUI.AssociationObj.ConnectionPoint.WEST);
                                    aObj.setPointTo(x4, y3);                                                                        
                                    
                                }
                                else
                                {                                    
                                    x1 = a2.getX() + a2.getWidth();
                                    y1 = a2.getY() + aObj.TOES;
                                    x4 = a1.getX();
                                    y3 = a1.getY() + aObj.FROMES;
                                    aObj.setFromConnectionPoint(TouchUmlUI.AssociationObj.ConnectionPoint.WEST);
                                    aObj.setPointFrom(x1, y1);
                                    aObj.setToConnectionPoint(TouchUmlUI.AssociationObj.ConnectionPoint.EAST);
                                    aObj.setPointTo(x4, y3);                                    
                                }
                            }
                            else if (a1.getY() + a1.getHeight() < a2.getY())
                            {
                                x1 = a1.getX() + aObj.FROMNS;
                                y1 = a1.getY() + a1.getHeight();                                                                
                                x3 = a2.getX() + aObj.TONS;                                
                                y4 = a2.getY();
                                aObj.setFromConnectionPoint(TouchUmlUI.AssociationObj.ConnectionPoint.SOUTH);
                                aObj.setToConnectionPoint(TouchUmlUI.AssociationObj.ConnectionPoint.NORTH);
                                aObj.setPointFrom(x1, y1);
                                aObj.setPointTo(x3, y4);
                            }
                            else if (a2.getY() + a2.getHeight() < a1.getY())
                            {
                                x1 = a2.getX() + aObj.TONS;
                                y1 = a2.getY() + a2.getHeight();                                
                                x3 = a1.getX() + aObj.FROMNS;                                
                                y4 = a1.getY();                                
                                aObj.setFromConnectionPoint(TouchUmlUI.AssociationObj.ConnectionPoint.NORTH);
                                aObj.setToConnectionPoint(TouchUmlUI.AssociationObj.ConnectionPoint.SOUTH);
                                aObj.setPointFrom(x1,y1);
                                aObj.setPointTo(x3,y4);
                            }
                            aObj.calculatePolyline();
                    }                   
                    aObj.updateEndings(false);                    
            }

            BringObjectsToFront();

            //List<KeyValuePair<AssociationObj, bool>> eastL = new List<KeyValuePair<AssociationObj, bool>>();
            //List<KeyValuePair<AssociationObj, bool>> westL = new List<KeyValuePair<AssociationObj, bool>>();
            //List<KeyValuePair<AssociationObj, bool>> northL = new List<KeyValuePair<AssociationObj, bool>>();
            //List<KeyValuePair<AssociationObj, bool>> southL = new List<KeyValuePair<AssociationObj, bool>>();

            //count[0] = count[1] = count[2] = count[3] = 0;
            //foreach (AssociationObj aObj in associationObj)
            //{
            //    if (aObj.fromRef.Equals(this))
            //    {
            //        if (aObj.getFromConnectionPoint() == AssociationObj.ConnectionPoint.EAST)
            //        {
            //            eastL.Add(new KeyValuePair<AssociationObj,bool>(aObj,true));
            //            count[0]++;
            //        }
            //        if (aObj.getFromConnectionPoint() == AssociationObj.ConnectionPoint.WEST)
            //        {
            //            westL.Add(new KeyValuePair<AssociationObj, bool>(aObj, true));
            //            count[1]++;
            //        }
            //        if (aObj.getFromConnectionPoint() == AssociationObj.ConnectionPoint.NORTH)
            //        {
            //            northL.Add(new KeyValuePair<AssociationObj, bool>(aObj, true));
            //            count[2]++;
            //        }
            //        if (aObj.getFromConnectionPoint() == AssociationObj.ConnectionPoint.SOUTH)
            //        {
            //            southL.Add(new KeyValuePair<AssociationObj, bool>(aObj, true));
            //            count[3]++;
            //        }
            //    }
            //    else if (aObj.toRef.Equals(this)) 
            //    {
            //        if (aObj.getToConnectionPoint() == AssociationObj.ConnectionPoint.EAST)
            //        {
            //            eastL.Add(new KeyValuePair<AssociationObj, bool>(aObj, false));
            //            count[0]++;
            //        }
            //        if (aObj.getToConnectionPoint() == AssociationObj.ConnectionPoint.WEST)
            //        {
            //            westL.Add(new KeyValuePair<AssociationObj, bool>(aObj, false));
            //            count[1]++;
            //        }
            //        if (aObj.getToConnectionPoint() == AssociationObj.ConnectionPoint.NORTH)
            //        {
            //            northL.Add(new KeyValuePair<AssociationObj, bool>(aObj, false));
            //            count[2]++;
            //        }
            //        if (aObj.getToConnectionPoint() == AssociationObj.ConnectionPoint.SOUTH)
            //        {
            //            southL.Add(new KeyValuePair<AssociationObj, bool>(aObj, false));
            //            count[3]++;
            //        }
            //    }
            //}

            //Console.WriteLine("EAST [{0}] WEST[{1}] NORTH[{2}] SOUTH[{3}]",count[0],count[1],count[2],count[3]);

            //// dla kazdej ze scian
            ///* EAST */
            //if (count[0] > 1)
            //{
            //    int startPoint = eastL.Count % 2 == 0 ? -10 : 0;
            //    if (eastL.Count % 2 == 0)
            //        startPoint = startPoint - ((eastL.Count - 2) / 2) * 20;
            //    else
            //        startPoint = startPoint - ((eastL.Count - 1) / 2) * 20;                
            //    foreach (KeyValuePair<AssociationObj, bool> aso in eastL)
            //    {
            //        if (aso.Value == true)
            //        {
            //            aso.Key.Move(startPoint, AssociationObj.AssociactionDirection.FROM);                                                
            //        }
            //        else
            //        {                        
            //            aso.Key.Move(startPoint, AssociationObj.AssociactionDirection.TO);
            //        }
            //        aso.Key.calculatePolyline();
            //        aso.Key.updateEndings(false);
            //        startPoint += 20;                    
            //    }               
            //}

            ///* WEST */
            //if (count[1] > 1)
            //{
            //    int startPoint = westL.Count % 2 == 0 ? -10 : 0;
            //    if (westL.Count % 2 == 0)
            //        startPoint = startPoint - ((westL.Count - 2) / 2) * 20;
            //    else
            //        startPoint = startPoint - ((westL.Count - 1) / 2) * 20;
            //    foreach (KeyValuePair<AssociationObj, bool> aso in westL)
            //    {
            //        if (aso.Value == true)
            //        {
            //            aso.Key.Move(startPoint, AssociationObj.AssociactionDirection.FROM);
            //         }
            //        else
            //        {
            //            aso.Key.Move(startPoint, AssociationObj.AssociactionDirection.TO);
            //        }
            //        aso.Key.calculatePolyline();
            //        aso.Key.updateEndings(false);
            //        startPoint += 20;
            //    }
            //}       

            ///* NORTH */
            //if (count[2] > 1)
            //{
            //    int startPoint = northL.Count % 2 == 0 ? -10 : 0;
            //    if (northL.Count % 2 == 0)
            //        startPoint = startPoint - ((northL.Count - 2) / 2) * 20;
            //    else
            //        startPoint = startPoint - ((northL.Count - 1) / 2) * 20;
            //    foreach (KeyValuePair<AssociationObj, bool> aso in northL)
            //    {
            //        if (aso.Value == true)
            //        {
            //            aso.Key.Move(startPoint, AssociationObj.AssociactionDirection.FROM);
            //        }
            //        else
            //        {
            //            aso.Key.Move(startPoint, AssociationObj.AssociactionDirection.TO);
            //        }
            //        aso.Key.calculatePolyline();
            //        aso.Key.updateEndings(false);
            //        startPoint += 20;
            //    }
            //}

            ///* SOUTH */
            //if (count[3] > 1)
            //{
            //    int startPoint = southL.Count % 2 == 0 ? -10 : 0;
            //    if (southL.Count % 2 == 0)
            //        startPoint = startPoint - ((southL.Count - 2) / 2) * 20;
            //    else
            //        startPoint = startPoint - ((southL.Count - 1) / 2) * 20;
            //    foreach (KeyValuePair<AssociationObj, bool> aso in southL)
            //    {
            //        if (aso.Value == true)
            //        {
            //            aso.Key.Move(startPoint, AssociationObj.AssociactionDirection.FROM);                        
            //        }
            //        else
            //        {
            //            aso.Key.Move(startPoint, AssociationObj.AssociactionDirection.TO);                        
            //        }
            //        aso.Key.calculatePolyline();
            //        aso.Key.updateEndings(false);
            //        startPoint += 20;
            //    }
            //}

            callReturn = true;

        }

    }
}
